#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdbool.h>

// 配置常量
#define SERVER_IP "192.168.2.87" // 服务器IP地址
#define SERVER_PORT 60000		  // 服务器端口号
#define BUFFER_SIZE 1024		  // 消息缓冲区大小
#define MAX_CLIENTS 10			  // 最大客户端数量

// 客户端状态枚举
typedef enum
{
	STATE_UNREGISTERED, // 未注册
	STATE_REGISTERED,	// 已注册未登录
	STATE_LOGGED_IN		// 已登录
} client_state;

// 全局变量
int client_socket = -1;					 // 客户端套接字
pthread_t recv_thread;					 // 接收线程
int running = 1;						 // 运行标志
client_state state = STATE_UNREGISTERED; // 客户端状态
bool need_prompt = true;				 // 输入提示标志

// 错误处理函数
void handle_error(const char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}

// 接收服务器消息线程
void *receive_messages(void *arg)
{
	char buffer[BUFFER_SIZE] = {0};

	while (running)
	{
		int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);
		if (bytes_received <= 0)
		{
			printf("Server disconnected. Press Enter to exit.\n");
			running = 0;
			break;
		}

		buffer[bytes_received] = '\0';
		
		printf("%s\n", buffer);

		// 自动更新状态
		if (strstr(buffer, "Registration successful") != NULL)
		{
			state = STATE_REGISTERED;
			printf("状态已更新：已注册\n");
		}
		else if (strstr(buffer, "Login successful") != NULL)
		{
			state = STATE_LOGGED_IN;
			printf("状态已更新：已登录\n");
		}
		else if (strstr(buffer, "Logout") != NULL || strstr(buffer, "Session expired") != NULL)
		{
			state = STATE_UNREGISTERED;
			printf("状态已更新：未注册\n");
		}
		// 确保用户输入提示与服务器响应分离
		if (running)
		{
			need_prompt = true;
		}
		sleep(1);
	}
	return NULL;
}

// 显示状态提示
void show_prompt()
{
	
	if (state == STATE_UNREGISTERED)
	{
		printf("[未注册]输入命令 (register/exit): ");
	}
	else if (state == STATE_REGISTERED)
	{
		printf("[已注册]输入命令 (login/exit): ");
	}
	else if (state == STATE_LOGGED_IN)
	{
		printf("[已登录]输入命令('/pm <id> '/'list' '/help' '/exit'): ");
	}
	fflush(stdout); // 刷新输出缓冲区
}

// 注册功能
void register_user()
{
	char username[50], password[50];
	printf("Enter username: ");
	scanf("%s", username);
	printf("Enter password: ");
	scanf("%s", password);

	char command[BUFFER_SIZE];
	snprintf(command, BUFFER_SIZE, "register %s %s", username, password);
	send(client_socket, command, strlen(command), 0);
}

// 登录功能
void login_user()
{
	char username[50], password[50];
	printf("Enter username: ");
	scanf("%s", username);
	printf("Enter password: ");
	scanf("%s", password);

	char command[BUFFER_SIZE];
	snprintf(command, BUFFER_SIZE, "login %s %s", username, password);
	send(client_socket, command, strlen(command), 0);
}

// 发送广播消息
void send_broadcast(const char *message)
{
	send(client_socket, message, strlen(message), 0);
	printf("广播消息: %s\n", message);
}

// 发送私聊消息
void send_private(int recipient_id, const char *message)
{
	char command[BUFFER_SIZE];
	snprintf(command, BUFFER_SIZE, "pm %d %s", recipient_id, message);
	send(client_socket, command, strlen(command), 0);
	printf("私聊用户 %d: %s\n", recipient_id, message);
}

// 显示帮助信息
void show_help()
{
	printf("\n可用命令:\n");
	printf("  /list       - 显示在线客户端\n");
	printf("  /pm <id>    - 向指定ID用户发送私信\n");
	printf("  /help       - 显示此帮助信息\n");
	printf("  /exit       - 退出聊天\n");
	printf("其他输入将作为广播消息发送\n\n");
}

// 主函数
int main()
{
	// 创建套接字
	client_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (client_socket == -1)
		handle_error("Socket creation failed");

	// 配置服务器地址
	struct sockaddr_in server_addr = {
		.sin_family = AF_INET,
		.sin_port = htons(SERVER_PORT),
		.sin_addr.s_addr = inet_addr(SERVER_IP)};

	// 连接服务器
	if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
		handle_error("Connect failed");

	printf("Connected to server %s:%d", SERVER_IP, SERVER_PORT);
	// printf("Welcome to the chat server!\nPlease register or login\n");

	// 创建接收线程
	if (pthread_create(&recv_thread, NULL, receive_messages, NULL) != 0)
		handle_error("Thread creation failed");
	pthread_detach(recv_thread);

	char input[BUFFER_SIZE] = {0};
	while (running)
	{
		sleep(1);
		// 根据状态显示提示符
		if (need_prompt) 
		{
            show_prompt();
            need_prompt = false;
        }

		if (fgets(input, BUFFER_SIZE, stdin) == NULL)
			continue;
		input[strcspn(input, "\n")] = 0; // 移除换行符

		// 处理退出命令
		if (strcmp(input, "exit") == 0 || strcmp(input, "/exit") == 0)
		{
			running = 0;
			break;
		}

		// 未注册状态处理
		if (state == STATE_UNREGISTERED)
		{
			if (strcmp(input, "register") == 0)
			{
				register_user();
			}
			else
			{
				printf("无效命令，可用: register/exit\n");
			}
			continue;
		}

		// 已注册未登录状态处理
		if (state == STATE_REGISTERED)
		{
			if (strcmp(input, "login") == 0)
			{
				login_user();
			}
			else
			{
				printf("无效命令，可用: login/exit\n");
			}
			continue;
		}

		// 已登录状态处理
		if (state == STATE_LOGGED_IN)
		{
			if (strcmp(input, "/help") == 0)
			{
				show_help();
			}
			else if (strcmp(input, "/list") == 0)
			{
				send(client_socket, "list", 4, 0);
				printf("------请求在线用户列表------\n");
			}
			else if (strncmp(input, "/pm ", 4) == 0)
			{
				char *id_str = input + 4;
				char *msg = strchr(id_str, ' ');
				if (msg)
				{
					*msg = '\0';
					int recipient_id = atoi(id_str);
					if (recipient_id >= 0 && recipient_id < MAX_CLIENTS)
					{
						send_private(recipient_id, msg + 1);
					}
					else
					{
						printf("无效的用户ID\n");
					}
				}
				else
				{
					printf("用法: /pm <id> <消息>\n");
				}
			}
			else
			{
				// 广播消息
				send_broadcast(input);
			}
		}
	}

	close(client_socket);
	printf("已断开连接\n");
	return 0;
}